﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace Utity
{
    public class AESSupport
    {
        /// <summary>  
        /// AES加密  
        /// </summary>  
        /// <param name="data">被加密的明文</param>  
        /// <param name="encryptKey">密钥（长度<=8）</param>  
        /// <param name="iv">向量（长度<=8）</param>  
        /// <returns>密文</returns>  
        public static String AESEncryptIV(String data, String encryptKey="", String iv="")
        {
                if (string.IsNullOrEmpty(iv))
                {
                    iv = GetAppIVt();
                }

                if (string.IsNullOrEmpty(encryptKey))
                {
                    encryptKey = GetAppKeyt();
                } 
                byte[] rgbKey = Encoding.UTF8.GetBytes(adjust8Length(encryptKey));
                byte[] rgbIV = Encoding.UTF8.GetBytes(adjust8Length(iv));
                byte[] inputByteArray = Encoding.UTF8.GetBytes(data);
                DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
                dCSP.Mode = CipherMode.CBC;
                dCSP.Padding = PaddingMode.PKCS7;
                MemoryStream mStream = new MemoryStream();
                CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
                cStream.Write(inputByteArray, 0, inputByteArray.Length);
                cStream.FlushFinalBlock();

                return Convert.ToBase64String(mStream.ToArray());
        }

        /// <summary>  
        /// AES解密  
        /// </summary>  
        /// <param name="data">被解密的密文</param>  
        /// <param name="encryptKey">密钥（长度<=8）</param>  
        /// <param name="iv">向量（长度<=8）</param>  
        /// <returns>明文</returns>  
        public static String AESDecryptIV(String data, String encryptKey = "", String iv = "")
        {
            if (string.IsNullOrEmpty(iv))
            {
                iv = GetAppIVt();
            }

            if (string.IsNullOrEmpty(encryptKey))
            {
                encryptKey = GetAppKeyt();
            }
            byte[] rgbKey = Encoding.UTF8.GetBytes(adjust8Length(encryptKey));
            byte[] rgbIV = Encoding.UTF8.GetBytes(adjust8Length(iv));
            byte[] inputByteArray = Convert.FromBase64String(data);
            DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
            dCSP.Mode = CipherMode.CBC;
            dCSP.Padding = PaddingMode.PKCS7;
            MemoryStream mStream = new MemoryStream();
            CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
            cStream.Write(inputByteArray, 0, inputByteArray.Length);
            cStream.FlushFinalBlock();
            return Encoding.UTF8.GetString(mStream.ToArray());
        }

        /// <summary>  
        /// AES加密(无向量)  
        /// </summary>  
        /// <param name="plainBytes">被加密的明文</param>  
        /// <param name="key">密钥</param>  
        /// <returns>密文</returns>  
        public static string AESEncrypt(String data, String key)
        {
            if (string.IsNullOrEmpty(key))
            {
                key = GetAppKeyt();
            }

            MemoryStream mStream = new MemoryStream();
            RijndaelManaged aes = new RijndaelManaged();

            byte[] plainBytes = Encoding.UTF8.GetBytes(data);
            Byte[] bKey = new Byte[32];
            Array.Copy(Encoding.UTF8.GetBytes(key.PadRight(bKey.Length)), bKey, bKey.Length);

            aes.Mode = CipherMode.ECB;
            aes.Padding = PaddingMode.PKCS7;
            aes.KeySize = 128;
            //aes.Key = _key;  
            aes.Key = bKey;
            //aes.IV = _iV;  
            CryptoStream cryptoStream = new CryptoStream(mStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
            try
            {
                cryptoStream.Write(plainBytes, 0, plainBytes.Length);
                cryptoStream.FlushFinalBlock();
                return Convert.ToBase64String(mStream.ToArray());
            }
            finally
            {
                cryptoStream.Close();
                mStream.Close();
                aes.Clear();
            }
        }


        /// <summary>  
        /// AES解密(无向量)  
        /// </summary>  
        /// <param name="encryptedBytes">被加密的明文</param>  
        /// <param name="key">密钥</param>  
        /// <returns>明文</returns>  
        public static string AESDecrypt(String data, String key)
        {
            if (string.IsNullOrEmpty(key))
            {
                key = GetAppKeyt();
            }
            Byte[] encryptedBytes = Convert.FromBase64String(data);
            Byte[] bKey = new Byte[32];
            Array.Copy(Encoding.UTF8.GetBytes(key.PadRight(bKey.Length)), bKey, bKey.Length);

            MemoryStream mStream = new MemoryStream(encryptedBytes);
            //mStream.Write( encryptedBytes, 0, encryptedBytes.Length );  
            //mStream.Seek( 0, SeekOrigin.Begin );  
            RijndaelManaged aes = new RijndaelManaged();
            aes.Mode = CipherMode.ECB;
            aes.Padding = PaddingMode.PKCS7;
            aes.KeySize = 128;
            aes.Key = bKey;
            //aes.IV = _iV;  
            CryptoStream cryptoStream = new CryptoStream(mStream, aes.CreateDecryptor(), CryptoStreamMode.Read);
            try
            {
                byte[] tmp = new byte[encryptedBytes.Length + 32];
                int len = cryptoStream.Read(tmp, 0, encryptedBytes.Length + 32);
                byte[] ret = new byte[len];
                Array.Copy(tmp, 0, ret, 0, len);
                return Encoding.UTF8.GetString(ret);
            }
            finally
            {
                cryptoStream.Close();
                mStream.Close();
                aes.Clear();
            }
        }

        #region inner
        const string DEFAULT_KEY = "BBFFTT!@#QWE";
        const string DEFAULT_IV = "520Gg520";
        const string APP_KEYT = "KEYT";
        const string APP_IVT = "IVT";
        public static string GetAppKeyt()
        {
            string keyt = System.Configuration.ConfigurationManager.AppSettings[APP_KEYT];
            return string.IsNullOrEmpty(keyt) ? DEFAULT_KEY : keyt;
        }

        public static string GetAppIVt()
        {
            string ivt = System.Configuration.ConfigurationManager.AppSettings[APP_IVT];
            return string.IsNullOrEmpty(ivt) ? DEFAULT_IV : ivt;
        }

        static string adjust8Length(string str)
        {
            if (str.Length == 8) return str;
            return str.Length < 8 ? str.PadRight(8) : str.Substring(0, 8);
        }
        #endregion
    }
}
